package com.cnswhy.cloud.server.comsumer.consumer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.cnswhy.cloud.common.core.exception.BizException;
import com.cnswhy.cloud.common.core.mybatis.conditions.Wraps;
import com.cnswhy.cloud.common.rabbitmq.service.MessageService;
import com.cnswhy.cloud.common.redis.service.RedisService;
import com.cnswhy.cloud.server.common.entity.constant.AmqpExchange;
import com.cnswhy.cloud.server.common.entity.enumeration.PayType;
import com.cnswhy.cloud.server.common.entity.mq.OrderQueryMQ;
import com.cnswhy.cloud.server.comsumer.event.OrderQueryMqEvent;
import com.cnswhy.cloud.server.core.appservice.AppChargeMoneyService;
import com.cnswhy.cloud.server.core.appservice.AppSpellOrderService;
import com.cnswhy.cloud.server.core.channel.service.AliRoutePayService;
import com.cnswhy.cloud.server.core.channel.wxpay.model.WxpayServiceRp;
import com.cnswhy.cloud.server.core.channel.wxpay.utils.HttpUtil;
import com.cnswhy.cloud.server.core.channel.wxpay.utils.PayCommonUtil;
import com.cnswhy.cloud.server.core.channel.wxpay.utils.XMLUtil;
import com.cnswhy.cloud.server.core.constant.RedisConstant;
import com.cnswhy.cloud.server.core.entity.SysConfig;
import com.cnswhy.cloud.server.core.service.SysConfigService;
import com.github.binarywang.wxpay.bean.request.WxPayOrderCloseRequest;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jdom2.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

@Component
@Slf4j
public class OrderQueryMqConsumer implements OrderQueryMqEvent {
    @Autowired
    AppSpellOrderService appSpellOrderService;
    @Autowired
    RedisService redisService;
    @Autowired
    SysConfigService sysConfigService;
    @Autowired
    MessageService messageService;
    @Autowired
    AppChargeMoneyService appChargeMoneyService;
    @Autowired
    AliRoutePayService aliRoutePayService;
    @Autowired
    WxPayService wxPayService;

    @Override
    public void query(OrderQueryMQ orderQueryMQ) throws BizException {

        if (PayType.alipay.equals(orderQueryMQ.getPayType())) {
            String flag = (String) redisService.hget(RedisConstant.SYS_CONFIG_2,
                    RedisConstant.ali_route_pay);
            if("true".equals(flag)){
                String response = null;
                try {
                     response = aliRoutePayService.transQuery(orderQueryMQ.getOrderId());
                } catch (Exception e) {
                    orderQueryMQ.setQueryTimes(orderQueryMQ.getQueryTimes() + 1);
                    messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
                    return;
                }
                JSONObject jsonObject = JSON.parseObject(response);
                if ("0000".equals(jsonObject.getString("code"))) {
                    JSONObject data = JSON.parseObject(jsonObject.getString("data"));
                    if ("02".equals(data.getString("orderStatus"))) {
                        if (StringUtils.equals("SHOPPING", orderQueryMQ.getBody())) {
                            appSpellOrderService.saveOrderNotify(data.getString("orderId"), data.getString("sysOrderId"));
                        } else if (StringUtils.equals("BACK-SHOPPING", orderQueryMQ.getBody())) {
                            appSpellOrderService.notifyPay(data.getString("orderId"), data.getString("sysOrderId"));
                        } else if (StringUtils.equals("SPELL-SHOPPING", orderQueryMQ.getBody())) {
                            appSpellOrderService.notifySpellOrder(data.getString("sysOrderId"), data.getString("orderId"), PayType.alipay);
                        } else if (StringUtils.equals("UPGRADE", orderQueryMQ.getBody())) {
                            appSpellOrderService.upgradeOrder(data.getString("sysOrderId"), data.getString("orderId"), PayType.alipay);
                        } else {
                            appChargeMoneyService.charge(data.getString("orderId"), data.getString("sysOrderId"));
                        }
                    }else if(!"03".equals(data.getString("orderStatus"))){
                        orderQueryMQ.setQueryTimes(orderQueryMQ.getQueryTimes() + 1);
                        messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
                        return;
                    }
                } else {
                    orderQueryMQ.setQueryTimes(orderQueryMQ.getQueryTimes() + 1);
                    messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
                    return;
                }
            }else {
                // 支付宝支付查询
                AlipayTradeQueryResponse alipayTradeQueryResponse = new AlipayTradeQueryResponse();
                try {
                    alipayTradeQueryResponse = AlipayQuery(orderQueryMQ.getOrderId());
                } catch (AlipayApiException e) {
                    log.info(e.getErrCode(), "支付宝查询异常:" + e.getErrMsg() + orderQueryMQ.getOrderId());
                    e.printStackTrace();
                } catch (Exception e) {
                    return;
                }
                if (alipayTradeQueryResponse.isSuccess()) {
                    if ("TRADE_SUCCESS".equals(alipayTradeQueryResponse.getTradeStatus())) {
                        //订单成功处理
                        if (StringUtils.equals("SHOPPING", orderQueryMQ.getBody())) {
                            appSpellOrderService.saveOrderNotify(alipayTradeQueryResponse.getOutTradeNo(), alipayTradeQueryResponse.getTradeNo());
                        } else if (StringUtils.equals("BACK-SHOPPING", orderQueryMQ.getBody())) {
                            appSpellOrderService.notifyPay(alipayTradeQueryResponse.getOutTradeNo(), alipayTradeQueryResponse.getTradeNo());
                        } else if (StringUtils.equals("SPELL-SHOPPING", orderQueryMQ.getBody())) {
                            appSpellOrderService.notifySpellOrder(alipayTradeQueryResponse.getTradeNo(), alipayTradeQueryResponse.getOutTradeNo(), PayType.alipay);
                        } else if (StringUtils.equals("UPGRADE", orderQueryMQ.getBody())) {
                            appSpellOrderService.upgradeOrder(alipayTradeQueryResponse.getTradeNo(), alipayTradeQueryResponse.getOutTradeNo(), PayType.alipay);
                        } else {
                            appChargeMoneyService.charge(alipayTradeQueryResponse.getOutTradeNo(), alipayTradeQueryResponse.getTradeNo());
                        }
                    }
                } else {
                    orderQueryMQ.setQueryTimes(orderQueryMQ.getQueryTimes() + 1);
                    messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
                    return;
                }
            }
        } else if (PayType.wx.equals(orderQueryMQ.getPayType())) {
            try {
                WxPayOrderQueryRequest wxPayOrderQueryRequest = WxPayOrderQueryRequest.newBuilder()
                        .outTradeNo(orderQueryMQ.getOrderId()).build();
                WxPayOrderQueryResult orderQueryResult = wxPayService.queryOrder(wxPayOrderQueryRequest);
                log.info(JSON.toJSONString(orderQueryResult));
                if("SUCCESS".equals(orderQueryResult.getTradeState())){
                    return;
                }else if(orderQueryMQ.getQueryTimes() > 7){
                    //超时未支付，关闭订单
                    WxPayOrderCloseResult wxPayOrderCloseResult = wxPayService.closeOrder(WxPayOrderCloseRequest.newBuilder()
                            .outTradeNo(orderQueryMQ.getOrderId()).build());
                    log.info(JSON.toJSONString(wxPayOrderCloseResult));
                    return;
                }

            } catch (Exception e) {
                return;
            }
            orderQueryMQ.setQueryTimes(orderQueryMQ.getQueryTimes() + 1);
            messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
            return;
        }
    }

    public AlipayTradeQueryResponse AlipayQuery(String orderId) throws AlipayApiException {

        SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "aliPaySys"));
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", sysConfig.getConfigValue(), sysConfig.getValidateRules(), "json", "GBK", sysConfig.getConfigRules(), "RSA2");
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent("{" +
                "\"out_trade_no\":\"" + orderId + "\"," +
                "\"trade_no\":\"\"," +
                "\"org_pid\":\"\"," +
                "\"query_options\":[" +
                "\"trade_settle_info\"" +
                " ]" +
                "  }");
        AlipayTradeQueryResponse response = null;
        response = alipayClient.execute(request);
        log.info(JSON.toJSONString(response));
        return response;
    }

    public WxpayServiceRp WxpayQuery(String out_trade_no) {
        WxpayServiceRp wxpayServiceRp = new WxpayServiceRp();
        try {
            SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "wxPaySys").eq(SysConfig::getDisplayStatus, "1"));

            String appid = sysConfig.getConfigValue(); // appid
            String mch_id = sysConfig.getValidateRules(); // 商业
            String key = sysConfig.getConfigRules(); // key
            String currTime = PayCommonUtil.getCurrTime();
            String strTime = currTime.substring(8, currTime.length());
            String strRandom = PayCommonUtil.buildRandom(4) + "";
            String nonce_str = strTime + strRandom;
            // 设置package订单参数
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
            packageParams.put("appid", appid);
            packageParams.put("mch_id", mch_id);
            // 生成签名的时候需要你自己设置随机字符串
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("out_trade_no", out_trade_no);
            String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);
            packageParams.put("sign", sign);
            log.info("微信支付查询请求参数=appid={}，mch_id={}，nonce_str={}，out_trade_no={} ,sign={}", appid, mch_id, nonce_str, out_trade_no, sign);

            String requestXML = PayCommonUtil.getRequestXml(packageParams);
            log.info("微信支付请求参数=requestXML=[{}]", requestXML);
            String resXml = HttpUtil.postData("https://api.mch.weixin.qq.com/pay/orderquery", requestXML);

            Map map = new HashMap();
            try {
                map = XMLUtil.doXMLParse(resXml);
            } catch (JDOMException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (StringUtils.isNotEmpty(map.get("return_code").toString()) && map.get("return_code").toString().equals("SUCCESS")) {
                if (StringUtils.isNotEmpty(map.get("result_code").toString()) && map.get("result_code").toString().equals("SUCCESS")) {
                    if (StringUtils.isNotEmpty(map.get("trade_state").toString()) && map.get("trade_state").toString().equals("SUCCESS")) {
                        wxpayServiceRp.setResult_code("0000");
                        wxpayServiceRp.setResult_msg("交易成功");
                        wxpayServiceRp.setAttach(map.get("attach").toString());
                        wxpayServiceRp.setOut_trade_no(map.get("out_trade_no").toString());
                        wxpayServiceRp.setTransaction_id(map.get("transaction_id").toString());
                    } else if (StringUtils.isNotEmpty(map.get("trade_state").toString()) && map.get("trade_state").toString().equals("NOTPAY")) {
                        wxpayServiceRp.setResult_code("0100");
                        wxpayServiceRp.setResult_msg(map.get("trade_state_desc").toString());
                    } else if (StringUtils.isNotEmpty(map.get("trade_state").toString()) && map.get("trade_state").toString().equals("PAYERROR")) {
                        wxpayServiceRp.setResult_code("0001");
                        wxpayServiceRp.setResult_msg(map.get("trade_state_desc").toString());
                    } else {
                        wxpayServiceRp.setResult_code("0100");
                        wxpayServiceRp.setResult_msg(map.get("trade_state_desc").toString());
                    }
                } else if (StringUtils.isNotEmpty(map.get("result_code").toString()) && map.get("result_code").toString().equals("FAIL")) {
                    wxpayServiceRp.setResult_code("0001");
                    wxpayServiceRp.setResult_msg(map.get("err_code_des").toString());
                } else {
                    wxpayServiceRp.setResult_code("0001");
                    wxpayServiceRp.setResult_msg(map.get("err_code_des").toString());
                }

            } else if (StringUtils.isNotEmpty(map.get("return_code").toString()) && map.get("return_code").toString().equals("FAIL")) {
                wxpayServiceRp.setResult_code("0100");
                wxpayServiceRp.setResult_msg(map.get("return_msg").toString());
            } else {
                wxpayServiceRp.setResult_code("0100");
                wxpayServiceRp.setResult_msg("查询异常");
            }
            log.info("微信支付查询返回参数=Result_code={}，Result_msg={}，out_trade_no={}", wxpayServiceRp.getResult_code(), wxpayServiceRp.getResult_msg(), out_trade_no);

            return wxpayServiceRp;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

}
